package com.like;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.BlendMode;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.render.Texture;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;

/**
 * Created by Miroslaw Stanek on 21.12.2015.
 * Modified by Joel Dean
 */
public class CircleView extends Component implements Component.DrawTask, Component.EstimateSizeListener,
        Component.LayoutRefreshedListener {
    private int START_COLOR = Color.getIntColor("#FFFF5722");
    private int END_COLOR = Color.getIntColor("#FFFFC107");

    private ArgbEvaluator argbEvaluator = new ArgbEvaluator();

    private Paint circlePaint = new Paint();
    private Paint maskPaint = new Paint();

    private PixelMap tempBitmap;
    private Canvas tempCanvas;

    private float outerCircleRadiusProgress = 1f;
    private float innerCircleRadiusProgress = 0.8f;

    private int width = 0;
    private int height = 0;

    private int maxCircleSize;

    public CircleView(Context context) {
        super(context);
        init();
    }

    public CircleView(Context context, AttrSet attrs) {
        super(context, attrs);
        init();
    }

    public CircleView(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setLayoutRefreshedListener(this::onRefreshed);

        circlePaint.setStyle(Paint.Style.FILL_STYLE);
        circlePaint.setAntiAlias(true);
        maskPaint.setAntiAlias(true);
        maskPaint.setBlendMode(BlendMode.CLEAR);

        onRefreshed(this);
        addDrawTask(this::onDraw);
        invalidate();
    }

    /**
     * Set the size of the circle
     *
     * @param width  width
     * @param height height
     */
    public void setSize(int width, int height) {
        this.width = width;
        this.height = height;
        invalidate();
    }

    @Override
    public boolean onEstimateSize(int widthEstimatedConfig, int heightEstimatedConfig) {
        if (width != 0 && height != 0) {
            setEstimatedSize(width, height);
        }
        return true;
    }

    @Override
    public void onRefreshed(Component component) {
        maxCircleSize = component.getWidth() / 4;
        tempBitmap = Utils.createPixelMap(component.getWidth(), component.getHeight(), PixelFormat.ARGB_8888);
        tempCanvas = new Canvas(new Texture(tempBitmap));
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        tempCanvas.drawColor(0xffffff, Canvas.PorterDuffMode.CLEAR);
        tempCanvas.drawCircle(component.getWidth() / 2, component.getHeight() / 2,
                outerCircleRadiusProgress * maxCircleSize, circlePaint);
        tempCanvas.drawCircle(component.getWidth() / 2, component.getHeight() / 2,
                innerCircleRadiusProgress * maxCircleSize + 1, maskPaint);
        canvas.drawPixelMapHolder(new PixelMapHolder(tempBitmap), 0, 0, new Paint());
    }

    public void setInnerCircleRadiusProgress(float innerCircleRadiusProgress) {
        this.innerCircleRadiusProgress = innerCircleRadiusProgress;
        invalidate();
    }

    public void setOuterCircleRadiusProgress(float outerCircleRadiusProgress) {
        this.outerCircleRadiusProgress = outerCircleRadiusProgress;
        updateCircleColor();
        invalidate();
    }

    private void updateCircleColor() {
        float colorProgress = (float) Utils.clamp(outerCircleRadiusProgress, 0.5, 1);
        colorProgress = (float) Utils.mapValueFromRangeToRange(colorProgress, 0.5f, 1f, 0f, 1f);
        this.circlePaint.setColor(new Color((int) argbEvaluator.evaluate(colorProgress, START_COLOR, END_COLOR)));
    }

    public void setStartColor(int color) {
        START_COLOR = color;
        invalidate();
    }

    public void setEndColor(int color) {
        END_COLOR = color;
        invalidate();
    }
}